package libs

import (
	"config"
	"github.com/garyburd/redigo/redis"
	"time"
)

type MultiLine struct {
	CommandName string
	CommandArgs []interface{}
}

var (
	ErrNil    = redis.ErrNil
	RedisPool *redis.Pool
)

func init() {
	RedisPool = &redis.Pool{
		MaxIdle:     5,
		IdleTimeout: 300 * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", config.RedisServer)
			if err != nil {
				return nil, err
			}
			//redis auth, if not password set please remove this code
			if _, err := c.Do("AUTH", config.RedisPassword); err != nil {
				c.Close()
				return nil, err
			}
			if _, err := c.Do("SELECT", config.RedisDatabase); err != nil {
				c.Close()
				return nil, err
			}
			return c, nil
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			if time.Since(t) < time.Minute {
				return nil
			}
			_, err := c.Do("PING")
			return err
		},
	}
}

func NewMultiLine(name string, args ...interface{}) *MultiLine {
	return &MultiLine{
		CommandName: name,
		CommandArgs: args,
	}
}

func MultiExec(commands []*MultiLine) (replay interface{}, err error) {
	rds := RedisPool.Get()
	defer rds.Close()
	rds.Send("MULTI")
	for _, line := range commands {
		rds.Send(line.CommandName, line.CommandArgs...)
	}
	return rds.Do("EXEC")
}

func SetKey(key, value interface{}, expires int) error {
	rds := RedisPool.Get()
	defer rds.Close()
	_, err := rds.Do("SETEX", key, expires, value)
	return err
}

func LPop(key string) (string, error) {
	rds := RedisPool.Get()
	defer rds.Close()
	return redis.String(rds.Do("LPOP", key))
}

func RPush(key, value interface{}) error {
	rds := RedisPool.Get()
	defer rds.Close()
	_, err := rds.Do("RPUSH", key, value)
	return err
}

func LLen(key string) (int64, error) {
	rds := RedisPool.Get()
	defer rds.Close()
	return redis.Int64(rds.Do("LLEN", key))
}

func LTrim(key string, start, stop int64) error {
	rds := RedisPool.Get()
	defer rds.Close()
	_, err := rds.Do("LTRIM", key, start, stop)
	return err
}

func ExistsKey(key string) (bool, error) {
	rds := RedisPool.Get()
	defer rds.Close()
	return redis.Bool(rds.Do("EXISTS", key))
}
